package com.one.group.admin.excel;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.one.group.admin.mapper.ParkingSpaceMapper;
import com.one.group.enums.ResultEnum;
import com.one.group.exception.BusinessException;
import com.one.group.model.entity.Vehicle;
import com.one.group.service.VehicleService;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 车辆数据读取监听器
 */
@Slf4j
public class VehicleDataReadListener implements ReadListener<VehicleData> {

    /**
     * 每隔100条存储数据库，实际使用中可以100条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 100;

    /**
     * 缓存的数据
     */
    private List<VehicleData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    private VehicleService vehicleService;
    private ParkingSpaceMapper parkingSpaceMapper;
    private Long tenantId;

    // 小区名称到ID的映射缓存
    private Map<String, Long> cellNameToIdMap = new HashMap<>();

    // 车主类型映射
    private static final Map<String, Integer> OWNER_TYPE_MAP = new HashMap<>();
    static {
        OWNER_TYPE_MAP.put("业主", 1);
        OWNER_TYPE_MAP.put("租户", 2);
        OWNER_TYPE_MAP.put("访客", 3);
        OWNER_TYPE_MAP.put("其他", 4);
    }

    public VehicleDataReadListener() {
    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * @param vehicleService 车辆服务
     * @param parkingSpaceMapper 车位Mapper
     * @param tenantId 租户ID
     */
    public VehicleDataReadListener(VehicleService vehicleService, ParkingSpaceMapper parkingSpaceMapper, Long tenantId) {
        this.vehicleService = vehicleService;
        this.parkingSpaceMapper = parkingSpaceMapper;
        this.tenantId = tenantId;
        
        // 初始化时加载所有小区映射
        initCellNameMapping();
    }

    /**
     * 初始化小区名称到ID的映射
     */
    private void initCellNameMapping() {
        try {
            List<Map<String, Object>> cellList = parkingSpaceMapper.getAllCellsByTenantId(tenantId);
            for (Map<String, Object> cell : cellList) {
                String cellName = (String) cell.get("name");
                Long cellId = ((Number) cell.get("id")).longValue();
                cellNameToIdMap.put(cellName, cellId);
            }
        } catch (Exception e) {
            log.error("加载小区映射失败", e);
            throw new RuntimeException("加载小区映射失败: " + e.getMessage());
        }
    }

    /**
     * 这个每一条数据解析都会来调用
     * @param data 一行数据
     * @param context 分析上下文
     */
    @Override
    public void invoke(VehicleData data, AnalysisContext context) {
        cachedDataList.add(data);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     * @param context 分析上下文
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        saveData();
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据，开始存储数据库！", cachedDataList.size());

        List<Vehicle> vehicleList = cachedDataList.stream()
                .filter(data -> !StrUtil.isEmpty(data.getPlateNo()))
                .map(data -> {
                    try {
                        // 从缓存中获取小区ID
                        Long cellId = cellNameToIdMap.get(data.getCellName());
                        if (cellId == null) {
                            throw new BusinessException(ResultEnum.DATA_NOT_EXIST.getCode(),
                                String.format("车牌号[%s]的小区名称[%s]不存在!",
                                    data.getPlateNo(), data.getCellName()));
                        }

                        // 根据车主类型名称获取类型ID
                        Integer ownerType = OWNER_TYPE_MAP.get(data.getOwnerTypeName());
                        if (ownerType == null) {
                            throw new BusinessException(ResultEnum.DATA_NOT_EXIST.getCode(),
                                String.format("车牌号[%s]的车主类型[%s]不存在!",
                                    data.getPlateNo(), data.getOwnerTypeName()));
                        }

                        Vehicle vehicle = new Vehicle();
                        vehicle.setPlateNo(data.getPlateNo());
                        vehicle.setCellId(cellId);
                        vehicle.setOwnerName(data.getOwnerName());
                        vehicle.setContactPhone(data.getContactPhone());
                        vehicle.setOwnerType(ownerType);
                        vehicle.setRemark(data.getRemark());
                        vehicle.setCreatedTime(new Date());
                        vehicle.setUpdatedTime(new Date());
                        vehicle.setTenantId(tenantId);
                        return vehicle;
                    } catch (Exception e) {
                        throw new BusinessException(ResultEnum.DATA_PROCESS_ERROR.getCode(),
                            String.format("车牌号[%s]数据处理失败：%s，请检查数据格式是否正确",
                                data.getPlateNo(), e.getMessage()));
                    }
                }).collect(Collectors.toList());
        
        // 保存到数据库
        try {
            vehicleService.saveBatch(vehicleList);
        } catch (Exception e) {
            throw new BusinessException(ResultEnum.IMPORT_FAIL.getCode(), "批量保存车辆数据失败!");
        }

        log.info("存储数据库成功！");
    }
}
